package com.cx.mall.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.cx.mall.common.model.order.OrderInfo;
import com.cx.mall.pay.config.AlipayConfiguration;
import com.cx.mall.common.model.entity.PayLog;
import com.cx.mall.pay.service.IAlipayService;
import com.cx.mall.pay.service.IPayLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class AlipayServiceImpl implements IAlipayService {
    @Autowired
    private AlipayConfiguration alipayConfiguration;
    @Autowired
    private IPayLogService payLogService;
    @Autowired
    private StreamBridge streamBridge;
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public String pay(OrderInfo orderInfo) throws Exception {
        // 1.创建默认的支付宝客户端实例
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfiguration.getAlipayConfig());
        // 2.发送支付请求
        // AlipayTradePagePayRequest接口主要用于在PC网站上实现支付宝支付功能
        AlipayTradePagePayRequest alipayTradePagePayRequest = new AlipayTradePagePayRequest();
        // 设置异步通知地址
        alipayTradePagePayRequest.setNotifyUrl(alipayConfiguration.getNotifyUrl());
        // 设置返回地址
        alipayTradePagePayRequest.setReturnUrl(alipayConfiguration.getReturnUrl());
        // 构造业务请求参数（如果是电脑网页支付，product_code是必传参数）
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("out_trade_no", orderInfo.getOrderId());// 订单编号
        jsonObject.put("subject", orderInfo.getRecipients());
        jsonObject.put("body", orderInfo.getRecipients());
        jsonObject.put("total_amount", orderInfo.getTotalAmount());// 订单总金额
        jsonObject.put("product_code", "FAST_INSTANT_TRADE_PAY");// 固定配置
        alipayTradePagePayRequest.setBizContent(jsonObject.toJSONString());
        // 3.请求支付宝接口，拿到响应结果
        String result = alipayClient.pageExecute(alipayTradePagePayRequest).getBody();
        return result;
    }
    @Transactional
    @Override
    public void payNotify(Map<String, String[]> result) {
        // 支付流水号
        String no = result.get("trade_no")[0];
        // 订单编号
        String id = result.get("out_trade_no")[0];
        // 订单金额
        String trade_no = result.get("total_amount")[0];
        // 写支付日志
        PayLog payLog = new PayLog();
        payLog.setId(no);
        payLog.setOrderId(id);
        payLog.setAmount(BigDecimal.valueOf(Double.parseDouble(trade_no)));
        payLogService.save(payLog);

        // 发送事务消息，修改订单状态
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                Message<?> message = MessageBuilder
                        .withPayload(id)
                        // 以流水号作为事务Id发送消息,并去重
                        .setHeader("TRANSACTION_ID",no).build();
                if(redisTemplate.opsForValue().setIfAbsent("REQ_" + no,"1",10, TimeUnit.SECONDS)){
                    streamBridge.send("createOrderOutput-out-0", message);
                }
            }
        });
    }

    public  String query(String outTradeNo) throws Exception {
        /*
         * 如果支付日志表表存在数据，则直接返回
         * 否则查询支付宝交易订单
         */
        // 1.查询支付日志表
        PayLog payLog = payLogService.queryByOrderId(outTradeNo);
        if(payLog != null){
            return "TRADE_SUCCESS";
        }
        // 2.查询支付宝交易订单
        // 2.1 创建默认的支付宝客户端实例
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfiguration.getAlipayConfig());
        // 2.2 构造请求参数以调用接口
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        // 2.3 设置订单支付时传入的商户订单号
        model.setOutTradeNo(outTradeNo);
        // 2.4 发送查询请求
        request.setBizModel(model);
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            // 2.5 写支付日志
            payLog = new PayLog();
            payLog.setId(response.getTradeNo());
            payLog.setOrderId(outTradeNo);
            payLog.setAmount(BigDecimal.valueOf(Double.parseDouble(response.getTotalAmount())));
            payLogService.save(payLog);

            // 2.6 返回查询结果
            return "TRADE_SUCCESS";
        }else {
            return "TRADE_FAIL";
        }
    }

}
